import socket
import secretary
import json
import datetime

class server:
    
    server_secretary = None
    server_socket = None
    
    def __init__(self):
        self.server_secretary = secretary.log()

        self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.server_socket.bind(('0.0.0.0',1688))


    def shake_hand(self):
        self.server_socket.listen(3)
        self.server_secretary.log('Server started, waiting for connection')
        # self.server_socket.settimeout(1800)
        try:
            self.client_socket, self.client_address = self.server_socket.accept()
            self.server_secretary.log(f'Establishing a connection with the client: {self.client_address}')
        except socket.timeout:
            return 'Fail'
        finally:
            return 'Succeed'

    def speak(self, dict_data):
        """send fundtin, including waiting for A

        Args:
            dict_data (dict): the data to send

        Returns:
            str: 'Success' or something else
        """        
        json_data = json.dumps(dict_data)
        flag = 1
        while True:

            if self.client_address == None:
                self.server_secretary.log('Client not connected')
                return 'Client not connected'
            if flag > 5:
                self.server_secretary.log('Client not hearing')
                return 'Client not hearing'

            self.client_socket.sendall(f'`{json_data}'.encode())

            try:
                response = self.client_socket.recv(1).decode()
                if response == 'A':
                    self.server_secretary.log('Received client reply letter A')
                    return 'Succeed'
                else:
                    self.server_secretary.log('Received client reply, but not letter A')
                    if response == '`':
                        self.server_secretary.log('Unexpectedly find "`"')
            except socket.timeout:
                self.server_secretary.log(f'No reply received from the client, tried {flag} time')
                flag += 1
            

    def hear(self):
        """receive function, including replying A

        Returns:
            dict: the message dumped into json
            None: fail to decode the message
        """        
        message_received = self.client_socket.recv(10240).decode()
        self.client_socket.sendall('A'.encode())
        self.server_secretary.log(f'Received data and returned letter A, Data is as follow:\n{message_received}')
        if message_received.find('`') == -1:
            self.server_secretary.log('incorrect message form')
        else:
            message_received = message_received[1:]
            if message_received.find('`') == -1:
                try:
                    message_received = json.loads(message_received)
                    self.server_secretary.log('Message decoded fluently')
                    return message_received
                except json.decoder.JSONDecodeError:
                    self.server_secretary.log('Message decode error')
                    return None
            else:
                message_received = message_received[:message_received.find('`')]
                self.server_secretary.log('Received many messages, but only decode one in case of repeating')
                try:
                    message_received = json.loads(message_received)
                    self.server_secretary.log('Message decoded fluently')
                    return message_received
                except json.decoder.JSONDecodeError:
                    self.server_secretary.log('Message decode error')
                    return None
            

    def goodbye(self):
        self.client_address = None
        self.client_socket.close()
        
    
    def shutdown(self):
        self.server_socket.close()
        self.server_secretary.log('Data transfer completed, close server port')
        print('Data transfer completed, close server port')
